/** 发布订阅模式
 * 使用方式:
 * bus.on(eventName, cb): 绑定事件
 * bus.emit(eventName, params): 触发事件
 * bus.off(eventName, cb): 移除事件
 * bus.once(eventName, cb): 触发1次
*/ 
class EventBus {
  // 缓存事件
  events = {}; 

  // 绑定事件监听
  on(eventName, cb) {
    (this.events[eventName] ??= new Set()).add(cb)
  }

  // 触发事件监听
  emit(eventName, ...args) {
    this.events[eventName]?.forEach(cb => cb(...args))
  }

  // 移除事件监听
  off(eventName, cb) {
    this.events[eventName].delete(cb)
  }
  
  // 只触发1次事件
  once(eventName, cb) {
    const handler = (...args) => {
      cb(...args)
      this.off(eventName, handler)
    }
    this.on(eventName, handler)
  }
}

// 导出单例bus
export const bus = new EventBus()
